package org.x.usermod.aspect;

import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.fastjson2.JSONObject;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.scheduling.annotation.Async;
import org.springframework.beans.factory.annotation.Autowired;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.x.commonmod.enums.LogAsync;
import org.x.commonmod.util.IpUtil;
import org.x.usermod.entity.SysLog;
import org.x.usermod.service.ISysLogService;

import java.util.Date;

@Aspect
@Component
@Slf4j
public class LogAspect {

    @Autowired
    ISysLogService ISysLogService;

    // 定义切点：标注@LogAsync的方法
    @Pointcut("@annotation(org.x.commonmod.enums.LogAsync)")
    public void logPointcut() {}

    // 环绕通知实现日志记录
    @Around("logPointcut()")
    public Object recordLog(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        LogAsync logAnnotation = signature.getMethod().getAnnotation(LogAsync.class);

        // 记录方法开始执行时间
        long startTime = System.currentTimeMillis();
        Object result = null;
        try {
            // 执行目标方法
            result = joinPoint.proceed();
        } finally {
            // 异步记录日志（不会阻塞主线程）
            asyncRecordLog(joinPoint, logAnnotation, startTime, result);
        }
        return result;
    }

    // 异步日志记录方法
    @Async
    public void asyncRecordLog(ProceedingJoinPoint joinPoint,
                               LogAsync logAnnotation,
                               long startTime,
                               Object result) {
        long executionTime = System.currentTimeMillis() - startTime;
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        Object[] args = joinPoint.getArgs();

        // 构建日志内容
        StringBuilder logContent = new StringBuilder();
        logContent.append("【").append(logAnnotation.value()).append("】")
                .append(" 执行时间: ").append(executionTime).append("ms | ")
                .append("类: ").append(className)
                .append(" | 方法: ").append(methodName);

        if (logAnnotation.recordParams()) {
            logContent.append(" | 参数: ");
            for (Object arg : args) {
                logContent.append(arg).append(", ");
            }
            logContent.delete(logContent.length() - 2, logContent.length());
        }

        //拿到request
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        SysLog logEntity = new SysLog();
        logEntity.setAction(logAnnotation.value());
        logEntity.setDetail(JSONObject.toJSONString(logContent));
        logEntity.setIp(IpUtil.getIpAddress(request));
        logEntity.setCreatedTime(new Date());
        //@TODO
        logEntity.setTargetType("admin");
        try {
            logEntity.setUserId(Long.valueOf(StpUtil.getLoginId().toString()));
            logEntity.setTargetId(null);
        }catch (Exception exception){

        }finally {
            ISysLogService.save(logEntity);
        }
     //   log.info(logContent.toString());
    }
}

